<template>
	<view class="animate__animated ref-lm-animate"
		:class="computedAnimateClass"
		:style="{
      ...customStyle,
      '--animate-duration': `${duration}ms`,
      '--animate-delay': `${delay}ms`,
    }">
		<slot />
	</view>
</template>
 
<script>
	export default {
		name: "lm-animate",
		data() {
			return {
				delayShow: false,
				timer: null,
				observer: null,
				isInView: false
			};
		},
		props: {
			show: {
				type: Boolean,
				default: false,
			},
			entryClass: {
				type: String,
				default: "animate__fadeIn",
			},
			exitClass: {
				type: String,
				default: "animate__fadeOut",
			},
			duration: {
				type: Number,
				default: 1500,
			},
			delay: {
				type: Number,
				default: 0,
			},
			customStyle: {
				type: Object,
				default: () => ({}),
			},
			// 新增：是否启用可视区域检测 
			lazy: {
				type: Boolean,
				default: false
			},
			// 新增：可视区域触发模式 
			triggerMode: {
				type: String,
				default: "once", // once（默认）| always 
				validator: val => ['once', 'always'].includes(val)
			},
			// 新增：可视区域触发阈值
			intersectionRatio: {
				type: Number,
				default: 0.1
			}
		},
		computed: {
			computedAnimateClass() {
				// 懒加载模式：未进入可视区不应用动画
				if (this.lazy  && !this.isInView)  return ''
				
				// 常规动画处理 
				return this.show  ? this.entryClass  : this.exitClass  
			}
		},
		watch: {
			show: {
				handler(newVal) {
					// 延迟执行逻辑处理 
					if (this.timer)  clearTimeout(this.timer); 
					
					if (newVal) {
						this.delayShow  = newVal;
						this.$emit("open");
						this.timer  = setTimeout(() => {
							this.$emit("opened");
						}, this.entryClass  ? this.duration  + this.delay  : 0);
					} else {
						this.$emit("close");
						this.timer  = setTimeout(() => {
							this.delayShow  = newVal;
							this.$emit("closed");
						}, this.exitClass  ? this.duration  + this.delay  : 0);
					}
				},
				immediate: false,
			},
			// 新增：监听lazy属性变化
			lazy: {
				immediate: true,
				handler(newVal) {
					if (newVal) {
						this.$nextTick(() => {
							this.initIntersectionObserver(); 
						});
					} else if (this.observer)  {
						this.observer.disconnect(); 
						this.observer  = null;
						this.isInView  = true; // 非懒加载模式始终显示
					}
				}
			}
		},
		mounted() {
			if (!this.lazy)  {
				this.isInView  = true;
			} else {
				this.initIntersectionObserver(); 
			}
		},
		beforeDestroy() {
			if (this.observer)  {
				this.observer.disconnect(); 
				this.observer  = null;
			}
		},
		methods: {
			// 初始化可视区域观察器
			initIntersectionObserver() {
				if (this.observer)  return;
				
				// UniApp跨端兼容方案
				if (typeof uni !== 'undefined' && uni.createIntersectionObserver)  {
					this.initUniObserver(); 
				} else if (typeof window !== 'undefined' && window.IntersectionObserver) {
					this.initWebObserver(); 
				} else {
					// 环境不支持时不阻塞显示 
					console.warn('IntersectionObserver  not supported, fallback to default behavior');
					this.isInView  = true;
				}
			},
			
			// 初始化UniApp环境观察器
			initUniObserver() {
				this.observer  = uni.createIntersectionObserver(this,  {
					thresholds: [0, this.intersectionRatio] 
				});
				
				this.observer.relativeToViewport() 
					.observe('.ref-lm-animate', res => {
						if (res.intersectionRatio  >= this.intersectionRatio)  {
							this.handleInView(); 
							if (this.triggerMode  === 'once') {
								this.observer.disconnect(); 
							}
						} else if (this.triggerMode  === 'always') {
							this.isInView  = false;
						}
					});
			},
			
			// 初始化Web环境观察器
			initWebObserver() {
				this.observer  = new IntersectionObserver(entries => {
					entries.forEach(entry  => {
						if (entry.isIntersecting  && entry.intersectionRatio  >= this.intersectionRatio)  {
							this.handleInView(); 
							if (this.triggerMode  === 'once') {
								this.observer.disconnect(); 
							}
						} else if (this.triggerMode  === 'always') {
							this.isInView  = false;
						}
					});
				}, {
					threshold: this.intersectionRatio 
				});
				
				this.$nextTick(() => {
					const el = this.$el.querySelector('.ref-lm-animate')  || this.$el;
					if (el) this.observer.observe(el); 
				});
			},
			
			// 进入可视区域处理
			handleInView() {
				this.isInView  = true;
				this.$emit('in-view'); // 新增事件通知 
			},
			
			// 新增：外部可调用的重置方法
			resetObserver() {
				if (this.observer)  {
					this.observer.disconnect(); 
					this.observer  = null;
				}
				this.isInView  = false;
				this.initIntersectionObserver(); 
			}
		}
	}
</script>
 
<style lang="scss">
	@import './animate.css'; 
</style>